﻿using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
using System.Globalization;
using System.Threading.Tasks;
using InseSoft.Infraestructure;
using MvvmValidation;

namespace InseSoft.Models.Entities
{
    public abstract class Entity : ObservableObject, IDataErrorInfo, IValidatable, IEntity
    {
        #region Declarations

        private int id;

        #endregion

        #region Constructors

        protected Entity()
        {
            Validator = new ValidationHelper();
            DataErrorInfoAdapter = new DataErrorInfoAdapter(Validator);
            HookUpValidationNotification();
        }

        #endregion

        #region Properties

        public int Id
        {
            get { return id; }
            set
            {
                id = value;
                OnPropertyChanged(() => Id);
                OnPropertyChanged(() => FriendlyId);
            }
        }

        [NotMapped]
        public string FriendlyId
        {
            get { return Id > 0 ? Id.ToString(CultureInfo.InvariantCulture) : "Sin asignar"; }
        }

        protected ValidationHelper Validator { get; private set; }
        protected DataErrorInfoAdapter DataErrorInfoAdapter { get; set; }

        public string Error
        {
            get { return DataErrorInfoAdapter.Error; }
        }

        public string this[string columnName]
        {
            get { return DataErrorInfoAdapter[columnName]; }
        }

        public bool IsValid
        {
            get
            {
                return Validate().IsValid;
            }
        }
        
        #endregion

        #region Methods

        public virtual void ConfigureValidationRules()
        {
            
        }

        Task<ValidationResult> IValidatable.Validate()
        {
            return Validator.ValidateAllAsync();
        }

        public virtual ValidationResult Validate()
        {
            return Validator.ValidateAll();
        }
        
        private void HookUpValidationNotification()
        {
            // Due to limitation of IDataErrorInfo, in WPF we need to explicitly indicated that something has changed
            // about the property in order for the framework to look for errors for the property.
            Validator.ResultChanged += (o, e) =>
            {
                var propertyName = e.Target as string;
                if (!string.IsNullOrEmpty(propertyName))
                    OnPropertyChanged(propertyName);
            };
        }
        
        #endregion
    }
}
